﻿
namespace ZDS

open System
open System.Collections
open System.Collections.Generic

/// any way, "modification during iteration" is always unsafe
/// so here we just copy the size
/// alway like most of the containers, this iterator is NOT thread-safe
type ZArrStackIterator<'t>(m_array: 't[],m_top)=
    let mutable m_index = -1
    
    interface IDisposable with
        member this.Dispose() = 
            ()

    interface IEnumerator<'t> with
        member this.Current =
            m_array.[m_index]

    interface IEnumerator with
        member this.MoveNext() =
            m_index <- m_index + 1
            m_index <= m_top

        member this.Reset() =
            m_index <- -1

        member this.Current =
            box (this :> IEnumerator<'t>).Current
        
type ZArrayStack<'t> (m_capacity)= 
    // ##################### primary constructor
    let m_array = Array.zeroCreate<'t>(m_capacity)
    let mutable m_top = -1

    // ##################### members
    member this.Capacity = m_capacity
    member this.Size = m_top+1

    member this.Push value =
        if m_top = (m_capacity-1) then
            raise <| ZError(ErrorCode.Full)

        m_top <- m_top + 1
        m_array.[m_top] <- value

    member this.Pop() =
        if m_top = -1 then
            raise <| ZError(ErrorCode.Empty)

        let topop = m_array.[m_top]
        m_top <- m_top-1
        topop

    interface IEnumerable<'t> with
        member this.GetEnumerator() =
            new ZArrStackIterator<'t>(m_array,m_top) :> IEnumerator<'t>

    interface IEnumerable with
        member this.GetEnumerator() =
            new ZArrStackIterator<'t>(m_array,m_top) :> IEnumerator
            
